package com.cfuture08.eweb4j.mvc;

import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.cfuture08.eweb4j.mvc.action.Action;
import com.cfuture08.eweb4j.mvc.config.MVCConfigConstant;
import com.cfuture08.eweb4j.mvc.config.bean.FormBean;
import com.cfuture08.eweb4j.mvc.config.bean.MVCConfigBean;
import com.cfuture08.eweb4j.mvc.config.bean.Result;
import com.cfuture08.util.ReflectUtil;
import com.cfuture08.util.StringUtil;

public class DoAction {
	public static String checkAndDoAction(MVCConfigBean mvcBean,
			Map<String, String[]> map, HttpServletRequest req,
			HttpServletResponse res, PrintWriter out) throws Exception {
		// 实例化action
		Action action = (Action) Class.forName(mvcBean.getClazz())
				.newInstance();
		ReflectUtil aRu = new ReflectUtil(action);
		// formBean
		for (FormBean f : mvcBean.getFormBean()) {
			if (f.getClazz() != null && !"".equals(f.getClazz())) {
				Object fo = Class.forName(f.getClazz()).newInstance();
				// 利用反射，将参数注入到FormBean中去
				autoSetValue(fo, map);
				// 将FormBean注入到action中
				Method m = aRu.getMethod("set"
						+ StringUtil.toUpCaseFirst(f.getName()));
				if (m != null) {
					m.invoke(action, fo);
				}
			}
		}

		// 利用反射，将参数注入到Action中去
		autoSetValue(action, map);
		// 初始化action
		action.init(req, res);
		// 执行action
		String re = action.execute();

		for (Result r : mvcBean.getResult()) {
			if (re.equals(Action.AJAX)) {
				// ajax
				String ajax = (String)req.getAttribute(MVCConfigConstant.AJAX_ATTR);
				if (ajax != null){
					out.print(ajax);
				}
				return MVCConfigConstant.AJAX_TYPE;
			} else if (re.equals(Action.JSON)){
				//json
				String json = (String)req.getAttribute(MVCConfigConstant.JSON_ATTR);
				if (json != null){
					out.print(json);
				}
				return MVCConfigConstant.JSON_TYPE;
			} else if (re.equals(Action.JSON_OUT)){
				//jsonOut
				return MVCConfigConstant.JSON_TYPE;
			}else if (re.equals(Action.JSON_OUT)){
				//ajaxOut
				return MVCConfigConstant.JSON_TYPE;
			}else if (re.equals(r.getName()) || "".equals(re)) {
				String type = r.getType();
				String location = r.getLocation();
				if (MVCConfigConstant.REDIRECT_TYPE.equalsIgnoreCase(type)) {
					// 客户端重定向
					res.sendRedirect(location);
					return MVCConfigConstant.REDIRECT_TYPE;
				} else if (MVCConfigConstant.FORWARD_TYPE
						.equalsIgnoreCase(type)
						|| "".equals(type)) {
					// 服务端跳转
					req.getRequestDispatcher(location).forward(req, res);
					return MVCConfigConstant.FORWARD_TYPE;
				} else if (MVCConfigConstant.AJAX_TYPE.equalsIgnoreCase(type)) {
					// ajax
					return MVCConfigConstant.AJAX_TYPE;
				}
			}
		}

		return null;
	}

	private static void autoSetValue(Object o, Map<String, String[]> map)
			throws Exception {
		ReflectUtil ru = new ReflectUtil(o);
		// 利用反射，将参数注入到Action中去
		for (Iterator<String> it = map.keySet().iterator(); it.hasNext();) {
			String n = it.next();
			String[] value = map.get(n);
			String v = (value == null ? "" : value[0]);
			Method m = ru.getMethod("set" + StringUtil.toUpCaseFirst(n));

			if (m != null) {
				Class<?> clazz = m.getParameterTypes()[0];
				if (clazz.isAssignableFrom(int.class)) {
					if ("".equals(v.trim())){
						v = "0";
					}
					m.invoke(o, Integer.parseInt(v));
				} else if (clazz.isAssignableFrom(long.class)) {
					if ("".equals(v.trim())){
						v = "0";
					}
					m.invoke(o, Long.parseLong(v));
				} else if (clazz.isAssignableFrom(double.class)) {
					if ("".equals(v.trim())){
						v = "0.0";
					}
					m.invoke(o, Double.parseDouble(v));
				} else if (clazz.isAssignableFrom(float.class)) {
					if ("".equals(v.trim())){
						v = "0.0";
					}
					m.invoke(o, Float.parseFloat(v));
				} else if (clazz.isAssignableFrom(boolean.class)) {
					if ("".equals(v.trim())){
						v = "false";
					}
					m.invoke(o, Boolean.parseBoolean(v));
				} else if (clazz.isAssignableFrom(String.class)) {
					m.invoke(o, v);
				}
			}
		}
	}
}
